package com.qujia.station.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qujia.common.core.domain.UniversalRedisMessageDto;
import com.qujia.common.core.domain.entity.SysUser;
import com.qujia.common.enums.PayTypeEnum;
import com.qujia.common.enums.WxConsumptionMessageEnum;
import com.qujia.common.exception.BaseException;
import com.qujia.common.utils.StringUtils;
import com.qujia.customer.domain.RchReductionReq;
import com.qujia.customer.enums.ElectronCardType;
import com.qujia.station.domain.*;
import com.qujia.station.domain.dto.PhysicalCardIntegralDto;
import com.qujia.station.domain.dto.PhysicalCardOrderDto;
import com.qujia.station.domain.dto.StationOilGunDto;
import com.qujia.station.domain.vo.ReduActiVO;
import com.qujia.station.enums.*;
import com.qujia.station.mapper.*;
import com.qujia.station.service.*;
import com.qujia.system.domain.HttpUtils;
import com.qujia.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service("physicalCardOrderServiceImpl")
@Slf4j
public class PhysicalCardOrderServiceImpl implements IPhysicalCardOrderService {

    @Autowired
    private IPhysicalCardBalanceService physicalCardBalanceService;

    @Autowired
    private IPhysicalCardService physicalCardService;

    @Autowired
    private StationMapper stationMapper;

    @Autowired
    private StationOillGunMapper stationOillGunMapper;

    @Autowired
    private CouponActivityService couponActivityService;

    @Autowired
    private PayOrderMapper payOrderMapper;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private PayWayMapper payWayMapper;

    @Resource
    private OrderPrintService orderPrintService;

    @Autowired
    private IPayOrderService payOrderService;

    @Autowired
    private IOilService oilService;

    @Autowired
    private AppUserInfoMapper appUserInfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${message.channel}")
    private String channel;

    @Value("${qujia.payBaseUrl}")
    private String payBaseUrl;

    public static final String PHYSICAL_CARD_PAYMENT_METHOD="dkq";




    @Override
    @Transactional
    public PayOrder physicalCardConsumption(PhysicalCardOrderDto physicalCardOrderDto) {
        // 创建订单
        PayOrder payOrder = new PayOrder();
        PhysicalCard physicalCard = physicalCardService.selectPhysicalCard(physicalCardOrderDto.getPhysicalCardNo());
        if(Objects.isNull(physicalCard) || Objects.isNull(physicalCard.getEnterpriseId())
                || StringUtils.isEmpty(physicalCard.getStationId()) || Objects.isNull(physicalCardOrderDto.getConsumptionStationId())){
            throw new BaseException("实体卡不存在");
        }

        //判断是定额卡还是储值卡
        SysUser sysUser = new SysUser();
        SysAppUserInfo sysAppUserInfo = new SysAppUserInfo();
        if(physicalCardService.physicalCardType(physicalCard)){
            physicalCardOrderDto.setBalanceType(BalanceTypeEnum.RATION_CONSUMPTION.getValue());
            physicalCardOrderDto.setPayment(PhysicalCardPaymentEnum.RATION_CONSUMPTION.getValue());
        }else {
            physicalCardOrderDto.setBalanceType(BalanceTypeEnum.CONSUMPTION.getValue());
            physicalCardOrderDto.setPayment(PhysicalCardPaymentEnum.STORED_CONSUMPTION.getValue());
            // 消费者
            SysAppUserInfo appUserInfo = new SysAppUserInfo();
            appUserInfo.setStationId(physicalCard.getEnterpriseId());
            appUserInfo.setMobilePhone(physicalCard.getUserPhone());
            sysAppUserInfo = appUserInfoMapper.getOne(appUserInfo);
            if(Objects.isNull(sysAppUserInfo)) {
                sysUser = sysUserService.selectUserByPhoneNumber(physicalCard.getUserPhone(), physicalCard.getEnterpriseId());
            }
        }

        BigDecimal amount;
        // 获取油枪、油品信息
        StationOilGunDto stationOilGunDto = getOilGun(physicalCardOrderDto.getOilGun(), physicalCardOrderDto.getConsumptionStationId());

        // 通用卡区分油站、不区分油品
        Station station = stationMapper.selectStationById(physicalCardOrderDto.getConsumptionStationId());
        List<String> stationIdList = Arrays.stream(physicalCard.getStationId().split(",")).collect(Collectors.toList());
        if(!stationIdList.contains(String.valueOf(physicalCardOrderDto.getConsumptionStationId()))){
            throw new BaseException("不能在该油站消费");
        }
        // 判断卡类型和油品对应类型
        if(!ElectronCardType.GENERIC.getKey().equals(physicalCard.getCardType())){
            Oil oil = oilService.selectOilById(Long.valueOf(stationOilGunDto.getOilId()));
            if(Objects.nonNull(oil) && StringUtils.isNotEmpty(oil.getCardType())
                    && !oil.getCardType().equals(physicalCard.getCardType())){
                throw new BaseException("实体卡类型与该油品不匹配");
            }
        }

        BigDecimal oilLiters = physicalCardOrderDto.getAmount().divide(stationOilGunDto.getOilStationPrice(), 4, BigDecimal.ROUND_HALF_UP); //加油升数
        //实付金额减立减金额
        payOrder.setReceivableAmt(physicalCardOrderDto.getAmount()); // 应收金额
        BigDecimal discountAmt = BigDecimal.ZERO;
        BigDecimal rchReductionAmt =BigDecimal.ZERO;
        if (physicalCardOrderDto.getEnableDiscount() == null || physicalCardOrderDto.getEnableDiscount()) {
            //立减活动
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            ReduActiVO activitiesVO=new ReduActiVO();
            activitiesVO.setActivityUse("CSP");
            activitiesVO.setAmt(physicalCardOrderDto.getAmount());
            activitiesVO.setDateTime(sdf.format(new Date()));
            activitiesVO.setEnterpriseId(physicalCard.getEnterpriseId().intValue());
            activitiesVO.setOilId(stationOilGunDto.getOilId());
            activitiesVO.setOrderLiters(oilLiters.toString());
            activitiesVO.setStationId(physicalCardOrderDto.getConsumptionStationId().intValue());
            activitiesVO.setPaymentMethod(PHYSICAL_CARD_PAYMENT_METHOD);
            discountAmt=payOrderService.reductionActivitiesAmountCalculation(activitiesVO).setScale(2, BigDecimal.ROUND_HALF_UP);
            payOrder.setConsumeDiscountAmt(new BigDecimal(discountAmt.doubleValue()));

            String url = payBaseUrl+"/reductionActivity/getRchReductionAmt";

            RchReductionReq req=new RchReductionReq();
            req.setPhysicalCardNo(physicalCardOrderDto.getPhysicalCardNo());
            req.setAmt(physicalCardOrderDto.getAmount());
            req.setOilId(stationOilGunDto.getOilId().longValue());
            req.setOrderLiters(oilLiters.toString());
            req.setStationId(station.getStationId());
            String resultJson = "";
            try {
                resultJson = HttpUtils.connectPostUrl(url, JSON.toJSONString(req));
                JSONObject jsonObject = JSONObject.parseObject(resultJson);
                rchReductionAmt =jsonObject.getBigDecimal("rCHReductionAmt");
                discountAmt=discountAmt.add(rchReductionAmt);
                payOrder.setRechargeDiscountAmt(rchReductionAmt);
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("立减活动返回信息：{}" + resultJson);
            //实付金额减立减金额
            payOrder.setReceivableAmt(physicalCardOrderDto.getAmount()); // 应收金额
            BigDecimal amount1 = physicalCardOrderDto.getAmount();
            amount1=amount1.subtract(discountAmt).setScale(2, BigDecimal.ROUND_HALF_UP);
            if(amount1.compareTo(BigDecimal.ZERO)<1){
                amount1 = new BigDecimal(0.01).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
            physicalCardOrderDto.setAmount(amount1);
        }


        // 修改实体卡面额
        if(Objects.isNull(physicalCard.getPhysicalCardAmount())
                || (physicalCard.getPhysicalCardAmount().signum() == 0)
                || (physicalCard.getPhysicalCardAmount().compareTo(physicalCardOrderDto.getAmount()) < 0)){
            throw new BaseException("实体卡面额不足，充值");
        } else {
            // 计算消费后的余额
            amount = physicalCard.getPhysicalCardAmount().subtract(physicalCardOrderDto.getAmount());
            physicalCard.setPhysicalCardAmount(amount);
            physicalCardService.updatePhysicalCard(physicalCard);
            physicalCardOrderDto.setBalanceAmount(amount);
        }

        //组装增加充值记录
        PhysicalCardBalance physicalCardBalance = new PhysicalCardBalance();
        BeanUtils.copyProperties(physicalCardOrderDto,physicalCardBalance);
        physicalCardBalance.setEnterpriseId(physicalCard.getEnterpriseId());
        physicalCardBalance.setEnterpriseName(physicalCard.getEnterpriseName());
        physicalCardBalance.setStationId(station.getStationId().toString());
        physicalCardBalance.setStationName(station.getStationName());
        physicalCardBalance.setPayment(PhysicalCardPaymentEnum.STORED_CONSUMPTION.getValue());

        //订单立减活动优惠  可以判断这个字段 enableDiscount 判断是否参加优惠活动



        // 没有第三方渠道信息
//        PayWayForm payWayForm = getStationPosPayWay(physicalCardOrderDto.getConsumptionStationId());

        payOrder.setAmt(physicalCardOrderDto.getAmount());// 实收金额
        payOrder.setDiscountAmt(discountAmt);// 优惠金额
        payOrder.setDiscountCouponAmt(BigDecimal.ZERO);// 优惠券金额

        // 计算渠道费  目前不用计算渠道费
//        calculatorChannelFee(newPayOrder,payWay,amt);

//        payOrder.setChannelFeePayer(payWayForm.getChannelFeePayer()); //没有渠道手续费支付方0司机/1油企
        payOrder.setServiceCharge(BigDecimal.ZERO); //费率
//        newPayOrder.setCommission(commission.doubleValue()); //渠道费 没有渠道费 默认为0

        String orderNo= StringUtils.generateOrdNo();
        payOrder.setOrderNo(orderNo);//订单号
        physicalCardBalance.setBalanceNo(orderNo); //实体卡消费时的订单号和订单表一致

        payOrder.setCustomerPhone(physicalCard.getUserPhone());
        if(Objects.nonNull(sysAppUserInfo)){
            if(StringUtils.isNotEmpty(sysAppUserInfo.getBlogNickName())) {
                payOrder.setConsumer(sysAppUserInfo.getBlogNickName());
            }
            if(Objects.nonNull(sysAppUserInfo.getUserId())){
                payOrder.setConsumerId(sysAppUserInfo.getUserId());
            }
        }
        if(Objects.nonNull(sysUser)) {
            if(StringUtils.isNotEmpty(sysUser.getUserName())) {
                payOrder.setConsumer(sysUser.getUserName());
            }
            if(Objects.nonNull(sysUser.getUserId())){
                payOrder.setConsumerId(sysUser.getUserId());
            }
        }

        payOrder.setEnterpriseId(physicalCard.getEnterpriseId());
        payOrder.setEnterpriseName(physicalCard.getEnterpriseName());

        payOrder.setAppType(AppTypeEnum.POS.getValue()); // 支付容器：1微信2支付宝3pos机4双屏机
        payOrder.setPayType(PayTypeEnum.dkq.getType()); // 支付类型：wx,zfb,dzk,xj,yl,hyk,dkq
        payOrder.setOrderOriginType(OrderOriginTypeEnum.dkq.getValue()); //订单来源1小程序，2pos机，3双屏机

        payOrder.setStationName(station.getStationName());
        payOrder.setStationId(station.getStationId());                  //油站id
        //内部系统直接扣款
        payOrder.setStatus(PayOrderStatusEnum.PAY.getValue()); //创建订单 状态(0未支付，1，已支付)
        payOrder.setCreatedDate(new Date());           //创建时间
        payOrder.setPayDate(new Date());    // 支付时间不能为空，否则影响班结
        payOrder.setOilGun(physicalCardOrderDto.getOilGun()); //油枪号
        payOrder.setDzkAmt(BigDecimal.ZERO);             //电子卡金额

        payOrder.setOilPirce(stationOilGunDto.getOilStationPrice()); //油价 原价
        payOrder.setOrderType(stationOilGunDto.getOilClass()); // 油品类
        payOrder.setOilName(stationOilGunDto.getOilId().toString()); // 油品id


        payOrder.setOrderLiters(oilLiters); // 油升数
        payOrder.setOilPersonnelId(physicalCardOrderDto.getOilPersonnelId());//加油员id
//        payOrder.setPayWayId(payWayForm.getPayWayId());  // 没有第三方支付渠道
        payOrder.setUtmSource(UtmSourceEnum.OTHER.getValue());// 订单来源默认9   订单来源 1-扫码 9-其它
//        newPayOrder.setXJStatus(null);//小程序内现金支付：现金支付的状态（0申请1取消）

        log.info("实体卡创建消费记录physicalCardConsumption.physicalCardBalance：[{}]",JSONObject.toJSONString(physicalCardBalance));
        physicalCardBalanceService.addPhysicalCardBalance(physicalCardBalance); // 添加消费记录
        log.info("实体卡创建订单physicalCardConsumption.payOrder：[{}]",JSONObject.toJSONString(payOrder));
        payOrder.setInvoiceStatus(3);
        payOrderMapper.insertPayOrder(payOrder);  // 添加订单


        //更新充值立减金额
        try {
            RchReductionReq req=new RchReductionReq();
            req.setPhysicalCardNo(physicalCardOrderDto.getPhysicalCardNo());
            req.setAmt(payOrder.getAmt());
            req.setRCHReductionAmt(rchReductionAmt);
            String url2 = payBaseUrl+"/reductionActivity/updateBalance";
            String res = HttpUtils.connectPostUrl(url2, JSON.toJSONString(req));
            log.info("更新充值立减金额-{}",res);
        } catch (Exception e) {
            e.printStackTrace();
        }
//发券
        couponActivityService.physicalCardSendCoupon(payOrder);
        //打印小票
        orderPrintService.orderPrint(payOrder, amount);

        payOrder.setBalance(amount);

        // 绑定会员的实体卡消费触发积分规则
        PhysicalCardIntegralDto physicalCardIntegralDto = new PhysicalCardIntegralDto();
        physicalCardIntegralDto.setPhysicalCardNo(physicalCard.getPhysicalCardNo());
        physicalCardIntegralDto.setOrderNo(orderNo);
        physicalCardIntegral(physicalCard,physicalCardIntegralDto);

        return payOrder;

    }

    private StationOilGunDto getOilGun(String oilGun,Long stationId){
        //油品价格
        StationOilGunDto stationOilGunDto = new StationOilGunDto();
        stationOilGunDto.setGunName(oilGun);    // 枪号
        stationOilGunDto.setStationId(stationId);//油站id
        StationOilGunDto stationOilGun = stationOillGunMapper.selectStaGunInfo(stationOilGunDto);
        if(stationOilGun == null){
            throw new BaseException("创建订单失败，未找到油枪信息");
        }
        log.info("获取油枪信息physicalCardConsumption.newPayWayForm:[{}]",JSONObject.toJSONString(stationOilGun));
        return stationOilGun;
    }


//    /**实体卡 第三方支付费率 取自同油站下消费及微信的费率*/
//    public PayWayForm getStationPosPayWay(Long stationId) {
//        PayWayForm payWayForm=new PayWayForm();
//        payWayForm.setUseType(PayWayUseTypeEnum.CONSUME.getValue().toString());             //使用类型
//        payWayForm.setStationId(stationId);
//        payWayForm.setAppType(PayWayServiceChargeEnum.APPTYPE_WECHAT.getValue().toString());
//        PayWayForm newPayWayForm = payWayMapper.getOneStationPayWay(payWayForm); //获取该油站的支付类型
//
//        if (newPayWayForm == null) {
//            // 找不到查找随行付的
//            payWayForm.setAppType(null);
//            payWayForm.setPayType("1");
//            newPayWayForm = payWayMapper.getOneStationPayWay(payWayForm);
//        }
//        log.info("获取第三方渠道号physicalCardConsumption.newPayWayForm: [{}]", JSONObject.toJSONString(newPayWayForm));
//        return newPayWayForm;
//    }

    //已绑定会员的实体卡消费产生积分
    private void physicalCardIntegral(PhysicalCard physicalCard, PhysicalCardIntegralDto physicalCardIntegralDto){
        if(Objects.isNull(physicalCard.getAppUserId())){
            // 未绑定实体卡，不计算积分
            return;
        }
        // 消费产生积分
        UniversalRedisMessageDto dto = new UniversalRedisMessageDto();
        dto.setData(JSONObject.toJSONString(physicalCardIntegralDto));
        dto.setMessageType(WxConsumptionMessageEnum.PHYSICAL_CARD_CONSUMPTION_MESSAGE_PUSH.getValue());
        dto.setTitle(WxConsumptionMessageEnum.PHYSICAL_CARD_CONSUMPTION_MESSAGE_PUSH.getKey());

        redisTemplate.convertAndSend(channel, dto);
    }
}
